; listbox.asm
; basic list box

	.include "common.inc"
	.include "global.inc"
	.include "util.inc"
	.include "window.inc"
	.include "lbstruct.inc"
	.include "wutil.inc"
	.include "memory.inc"
	.include "execfun.inc"
	.include "drawfun.inc"
	.include "graphic.inc"
	.include "text.inc"
	.include "cursor.inc"

	.export lb_create
	.export lb_setcnt
	.export lb_redraw
	.export lb_getpos
	.export lb_getuser
	
	; from drawfun.asm
	.import style
	.import top
	.import left
	.import tdx
	.import tdy
	.import text
	.import drwwintxt
	
	lbcolx = left
	lbcoly = top
	lbcolwidth = tdx
	lbheight = tdy
	
	.segment "ZEROPAGE" : zeropage
	
lb_reg0:	.res 2	; ptr to LbCreateStruct
lb_reg1:	.res 2	; ptr to LbColumnStruct
lb_reg2:	.res 2	; ptr to LbStruct

	.segment "JMPTABLE"
	
gettext:	.word 0

	.segment "DATA"

lbmaxcols:	.byte 0
lbcurcol:	.byte 0
lbindex:	.byte 0
lblines:	.byte 0
lbline:		.byte 0
lbvline:	.byte 0
lbscrltop:	.byte 0
lbscrlleft:	.byte 0
lbscrlrght: .byte 0
lbscrlbot:	.byte 0
lbscrlhgt:	.byte 0
lbscrlend:	.byte 0
btncount:	.byte 0

	LB_BORDER_X = 1
	LB_BORDER_Y = 1
	
	LBB_DIM_X = 9
	LBB_DIM_Y = 10

	LBB_IDX_BEG = 0
	LBB_IDX_PGUP = 1
	LBB_IDX_UP = 2
	LBB_IDX_DN = 3
	LBB_IDX_PGDN = 4
	LBB_IDX_END = 5
	
	IND_MIN_HGT = 1

; Listbox data ptr table

	LB_MAX_WINDOWS = 16

blptrlo:	.REPEAT LB_MAX_WINDOWS
				.byte 0
			.ENDREP
blptrhi:	.REPEAT LB_MAX_WINDOWS
				.byte 0
			.ENDREP		

	.segment "CODE"
;
;	Create a listbox
;	INPUT:
;		A .. parent window
;		X/Y ... ptr to LbCreateStruct#LbColumnStruct(s)
;	OUTPUT:
;		A .. listbox index
;
lb_create:	; alloc list box structure
			stx lb_reg0
			sty	lb_reg0+1
			pha
			jsr lb_alloc
			ldy #LbStruct::config
			lda lb_reg0
			sta (lb_reg2), y
			iny
			lda lb_reg0+1
			sta (lb_reg2), y
			pla
			pha
			jsr win_select
			jsr win_getuser
			ldy #LbStruct::user
			sta (lb_reg2), y
			pla
			; create frame window
			jsr win_create
			ldy #LbStruct::window
			sta (lb_reg2), y
			lda #WSTYLE_BORDER|WSTYLE_BCKGND
			jsr win_setstyle
			ldy #LbCreateStruct::left
			lda (lb_reg0), y
			tax
			clc					; calc & save x(inner) for later
			adc #LB_BORDER_X
			ldy #LbStruct::sx
			sta (lb_reg2), y
			ldy #LbCreateStruct::top
			lda (lb_reg0), y
			pha
			clc					; calc & save y(inner) for later
			adc #LB_BORDER_Y
			ldy #LbStruct::sy
			sta (lb_reg2), y
			pla
			tay
			jsr win_setpos
			ldy #LbCreateStruct::width
			lda (lb_reg0), y
			tax
			sec					; calc & save inner width
			sbc #LB_BORDER_X+LBB_DIM_X
			ldy #LbStruct::iwidth
			sta (lb_reg2), y
			ldy #LbCreateStruct::height
			lda (lb_reg0), y
			pha					; calc & save inner height
			sec
			sbc #LB_BORDER_Y
			ldy #LbStruct::iheight
			sta (lb_reg2), y
			pla
			tay
			jsr win_setdim
			lda lbindex			; store lb index in frame window
			jsr win_setuser
			ldy #LbCreateStruct::font
			lda (lb_reg0), y
			jsr win_setfont
			lda #<ex_lb_frame
			ldx #>ex_lb_frame
			jsr win_setexec
			lda #<drw_lb_frame
			ldx #>drw_lb_frame
			jsr win_setdraw
			
			; create column headers
			ldy #LbCreateStruct::columns	; init column counter
			lda (lb_reg0), y
			sta lbmaxcols
			lda #0
			sta lbcurcol
			jsr lb_selcol
			ldy #LbCreateStruct::font		; get font dimensions
			lda (lb_reg0), y
			jsr getemsize
			tya					 ; set line height to text height
			ldy #LbStruct::lineheight
			sta (lb_reg2), y
			sta lbheight
			
			ldy #LbStruct::sx		; init col title coordinates
			lda (lb_reg2), y
			sta lbcolx
			ldy #LbStruct::sy
			lda (lb_reg2), y
			sta lbcoly
			sta lbscrltop
			clc						; calc item area top coord.
			adc lbheight
			adc #LB_BORDER_Y
			ldy #LbStruct::sy
			sta (lb_reg2), y
			sec
			ldy #LbStruct::iheight	; calc item area height
			lda (lb_reg2), y
			sbc lbheight
			sta (lb_reg2), y
@colloop:	lda lbcurcol			; max # of columns reached?
			cmp lbmaxcols
			bcs @donecols
			ldy #LbStruct::window		; create text window
			lda (lb_reg2), y
			jsr win_create
			ldy #LbColumnStruct::txpos_title
			lda (lb_reg1), y
			jsr win_setstyle
			ldx lbcolx
			ldy lbcoly
			jsr win_setpos
			ldy #LbColumnStruct::width
			lda (lb_reg1), y
			sta lbcolwidth
			tax
			ldy lbheight
			jsr win_setdim
			ldy #LbColumnStruct::title+1
			lda (lb_reg1), y
			tax
			dey
			lda (lb_reg1), y
			jsr win_settext
			
			lda lbcolwidth				; prepare next column
			clc
			adc lbcolx
			adc #LB_BORDER_X
			sta lbcolx
			; TODO: check for frame width (LbStruct::iwidth)?
			jsr lb_nextcol
			inc lbcurcol
			bne @colloop
			
			; create scroll buttons
@donecols:	dec lbscrltop
			ldy #LbCreateStruct::height	; calc scroll bar area
			lda (lb_reg0), y
			clc
			adc lbscrltop
			sta lbscrlbot
			ldy #LbCreateStruct::left
			lda (lb_reg0), y
			clc
			ldy #LbCreateStruct::width
			adc (lb_reg0), y
			sta lbscrlrght
			sec
			sbc #LBB_DIM_X
			sta lbscrlleft
			ldy #LbCreateStruct::height	; determine button space
			lda (lb_reg0), y
			ldx #LBB_DIM_Y
			jsr bdiv
			txa
			lsr
			sta btncount
			cmp #3						; beg/end buttons?
			bcc @chkpgbtns
			ldx #LBB_IDX_BEG
			lda #LBB_IDX_END
			jsr crtbtnpair
			
			lda btncount
@chkpgbtns:	cmp #2						; page buttons?
			bcc @chklnbtns				
			ldx #LBB_IDX_PGUP
			lda #LBB_IDX_PGDN
			jsr crtbtnpair

			lda btncount
@chklnbtns:	cmp #1						; up/dn buttons?
			bcc @nobtns
			ldx #LBB_IDX_UP
			lda #LBB_IDX_DN
			jsr crtbtnpair
			
			; create scroll indicator
@nobtns:	ldy #LbStruct::window		; create window
			lda (lb_reg2), y
			jsr win_create
			ldy #LbStruct::wscrlind
			sta (lb_reg2), y
			ldx lbscrlleft
			ldy lbscrltop
			jsr win_setpos
			sec
			lda lbscrlrght
			sbc lbscrlleft
			tax
			lda lbscrlbot
			sbc lbscrltop
			tay
			jsr win_setdim
			lda #<drwscrlind
			ldx #>drwscrlind
			jsr win_setdraw	
			lda lbindex					; assign lb index
			jsr win_setuser

			; calc visible lines
			ldy #LbStruct::iheight	; get item area height
			lda (lb_reg2), y
			ldx lbheight
			inx
			jsr bdiv
			ldy #LbStruct::vis_lines
			txa
			sta (lb_reg2), y			

			; init line counters to 0
			lda #0
			ldy #LbStruct::tot_lines
			sta (lb_reg2), y
			ldy #LbStruct::first_line
			sta (lb_reg2), y
			ldy #LbStruct::sel_line
			sta (lb_reg2), y
			
			lda lbindex
			rts

;
;	Set list box line count
;	INPUT:
;		A ... list box index
;		X ... line count
;

lb_setcnt:	sta lbindex
			stx lblines
			jsr lb_select
			ldy #LbStruct::tot_lines
			lda lblines
			sta (lb_reg2), y
			ldy #LbStruct::first_line
			lda (lb_reg2), y
			cmp lblines
			bcc @firstok
			ldx lblines
			beq @ndec
			dex
@ndec:		txa
			sta (lb_reg2), y ; y = LbStruct::first_line
			ldy #LbStruct::sel_line
			lda (lb_reg2), y
			cmp lblines
			bcc @firstok
			txa
			sta (lb_reg2), y 
@firstok:	rts

;
;	Gets current scroll bar position
;	INPUT:
;		A ... list box index
;	OUTPUT
;		A ... scroll bar position
;

lb_getpos:	sta lbindex
			jsr lb_select
			ldy #LbStruct::sel_line
			lda (lb_reg2), y
			rts

;
;	Redraw list box
;	INPUT:
;		A ... list box index
;

lb_redraw:	sta lbindex
			jsr lb_select
			ldy #LbStruct::window
			lda (lb_reg2), y
			jmp win_draw

;
;	Create a scoll button pair
;	INPUT:
;		X ... top button index
;		A ... bottom button index
;
crtbtnpair:	pha
			txa
			ldx lbscrlleft
			ldy lbscrltop
			jsr lb_newbut
			lda lbscrlbot
			sec
			sbc #LBB_DIM_Y
			tay
			pla
			ldx lbscrlleft
			jsr lb_newbut
;
;	Shrink scroll area by a button pair size
;
shrinkscrl:	clc
			lda lbscrltop
			adc #LBB_DIM_Y
			sta lbscrltop
			sec
			lda lbscrlbot
			sbc #LBB_DIM_Y
			sta lbscrlbot
			rts

;
;	Event handler for list box frame window
;

ex_lb_frame:
			ldy #Event::type
			lda (reg2), y
			cmp #EVT_WIN_DESTROY
			beq @close
			cmp #EVT_MOUSE_DOWN
			beq ex_lb_click
			jmp ex_window
@close:		jsr win_getuser
			sta lbindex
			jmp lb_free

;
;	Mouse click event in list box frame
;

ex_lb_click:
			jsr lb_selectw			; setup lb regs
			jsr win_begindraw
			jsr getmousrel
			sty lbby
			txa						; x in area?
			sec
			ldy #LbStruct::sx
			sbc (lb_reg2), y
			bcc @elcfin				; outside area (left)
			ldy #LbStruct::iwidth
			cmp (lb_reg2), y
			bcs @elcfin				; outside area (right)
			; clc from above
			ldy #LbStruct::sy		; set up top coord
			lda (lb_reg2), y		;   lbcoly := sy+LB_BORDER_Y
			adc #LB_BORDER_Y
			sta lbcoly
			ldy #LbStruct::lineheight	; X := lineheight+1
			lda (lb_reg2), y
			tax
			inx
									; calc line
			lda lbby				;  A := my - lbcoly
			sec
			sbc lbcoly
			bcc @elcfin				; outside area (top)
			jsr	bdiv				; X := (my - lbcoly) / (lineheight + 1)
			txa
			ldy #LbStruct::vis_lines ; check for visible area
			cmp (lb_reg2), y
			bcs @elcfin
			; clc
			ldy #LbStruct::first_line	; A := first_line + X
			adc (lb_reg2), y
			ldy #LbStruct::tot_lines	; A >= tot_lines ? 
			cmp (lb_reg2), y
			bcs @elcfin				; index out of range
			; A = clicked item line
			jmp movesel
@elcfin:	rts

;
;	Clear list box item area
;	INPUT:
;		(lb_reg2) ... LbStruct
;

clr_lbitms:	lda #GM_SET
			jsr g_mode
			ldy #LbStruct::sx
			lda (lb_reg2), y
			tax
			ldy #LbStruct::sy
			lda (lb_reg2), y
			tay
			iny
			jsr g_moveto
			ldy #LbStruct::iwidth
			lda (lb_reg2), y
			tax
			ldy #LbStruct::iheight
			lda (lb_reg2), y
			sec
			sbc #2*LB_BORDER_Y+1
			tay
			jsr g_block
			lda #GM_CLEAR
			jmp g_mode
			
;
;	Draw function for list box frame window
;

drw_lb_frame:
			jsr drw_window
			jsr lb_selectw
			ldy #LbStruct::sx	; draw header frame
			lda (lb_reg2), y
			tax
			ldy #LbStruct::sy
			lda (lb_reg2), y
			tay
			jsr g_moveto
			lda #GM_CLEAR
			jsr g_mode
			ldy #LbStruct::iwidth
			lda (lb_reg2), y
			tax
			jsr g_hline
			; fall through

;
;	Draw list box item area
;	INPUT:
;		(lb_reg2) ... LbStruct
;

drw_lbitms:	jsr lb_selconf				; set up structure ptrs
			lda #0						; check line counters
			sta lbvline
			ldy #LbStruct::first_line
			lda (lb_reg2), y
			sta lbline
			ldy #LbStruct::tot_lines
			cmp (lb_reg2), y
			bcs @fin
			
			; clc ... from above
			ldy #LbStruct::sy			; set up line coord
			lda (lb_reg2), y
			adc #LB_BORDER_Y
			sta lbcoly
			ldy #LbStruct::lineheight
			lda (lb_reg2), y
			sta lbheight
			
			ldy #LbCreateStruct::font	; select font
			lda (lb_reg0), y
			jsr t_font
			
@linelp:	jsr drw_lbline				; draw one line
			
			inc lbvline					; manage line counters
			lda lbvline
			ldy #LbStruct::vis_lines
			cmp (lb_reg2), y
			bcs @fin					; no more visible lines?
			inc lbline
			lda lbline
			ldy #LbStruct::tot_lines
			cmp (lb_reg2), y
			bcs @fin					; no more lines to draw ?

			sec							; advance line coord
			lda lbcoly
			adc lbheight	; lbcoly := lbcoly + lbheight + 1 (sec!)
			sta lbcoly
			
			jsr lb_selcol				; select first column
			jmp @linelp
						
@fin:		; fall through

;
;	Toggles line selection bar
;	INPUT:
;		(lb_reg2) ... LbStruct
;

lb_tglsel:	ldy #LbStruct::lineheight
			lda (lb_reg2), y
			sta lbheight
			ldy #LbStruct::sel_line	; calc rel. line & check visibility
			lda (lb_reg2), y
			ldy #LbStruct::tot_lines
			cmp (lb_reg2), y
			bcs @not_vis
			ldy #LbStruct::first_line
			sec		
			sbc (lb_reg2), y
			bcc @not_vis
			ldy #LbStruct::vis_lines
			cmp (lb_reg2), y
			bcs @not_vis
			
			ldx lbheight			; calc & draw bar
			inx
			jsr bmul
			clc
			ldy #LbStruct::sy
			adc (lb_reg2), y
			pha
			ldy #LbStruct::sx 
			lda (lb_reg2), y
			tax
			inx
			pla
			tay
			iny
			jsr g_moveto
			
			lda #GM_XOR
			jsr g_mode

			ldy #LbStruct::iwidth
			lda (lb_reg2), y
			tax
			dex
			dex
			ldy lbheight
			jsr g_block
			
@not_vis:	rts

;
;	Draws one list box item line
;	INPUT:
;		(lb_reg0) ... LbCreateStruct
;		(lb_reg1) ... column [0]
;		(lb_reg2) ... LbStruct
;		lbvline .... visible line no
;		lbline ..... abs line no.
;		lbcoly ..... current y coord (top)
;		lbheight ... line height
;

drw_lbline: ldy #LbStruct::sx		; init col coordinates
			lda (lb_reg2), y
			sta lbcolx
			ldy #LbCreateStruct::columns	; set up col cnt
			lda (lb_reg0), y
			sta lbmaxcols
			lda #0
			sta lbcurcol
			
@colloop:	lda lbcurcol			; max # of columns reached?
			cmp lbmaxcols
			bcs @donecols
			
			ldy #LbColumnStruct::txpos_item	; set up text output
			lda (lb_reg1), y
			sta style
			
			ldy #LbColumnStruct::width
			lda (lb_reg1), y
			sta lbcolwidth
			
			ldy #LbColumnStruct::get_text		; get item text
			lda (lb_reg1), y
			sta gettext
			iny
			lda (lb_reg1), y
			sta gettext+1
			
			ldx lbcurcol
			ldy lbline
			jsr lb_gettext
			
			sta text						; draw item text
			stx text+1
			jsr drwwintxt

			lda lbcolwidth				; prepare next column
			clc
			adc lbcolx
			adc #LB_BORDER_X
			sta lbcolx
			; TODO: check for frame width (LbStruct::iwidth)?
			jsr lb_nextcol
			inc lbcurcol
			bne @colloop
			
@donecols:	
			rts

lb_gettext:	jmp (gettext)

;
;	Gets listboxes parent user data
;	INPUT:
;		(lb_reg2) ... LbStruct
;	OUTPUT:
;		A ... user data of parent window or 0.
;

lb_getuser:	ldy #LbStruct::user
			lda (lb_reg2), y
			rts

;
;	Create scroll bar button
;	INPUT:
;		A ........... Button index
;		X/Y	......... Button position
;		(lb_reg2) ... LbStruct
;		lbindex ..... List box index
;
		.segment "DATA"

lbbidx:		.byte 0
lbbx:		.byte 0
lbby:		.byte 0

		.segment "CODE"

lb_newbut:	sta lbbidx
			stx lbbx
			sty lbby
			ldy #LbStruct::window		; create window
			lda (lb_reg2), y
			jsr win_create
			lda #WSTYLE_BORDER
			jsr win_setstyle
			ldx lbbx
			ldy lbby
			jsr win_setpos
			ldx #LBB_DIM_X
			ldy #LBB_DIM_Y
			jsr win_setdim
			ldy	lbbidx					; set symbol
			lda lbbtxlo, y
			ldx lbbtxhi, y
			jsr win_settext
			lda #WTYPE_BUTTON			; make button
			jsr win_settype
			lda lbindex					; assign lb index
			jsr win_setuser
			ldy	lbbidx					; set exec func
			lda lbbexlo, y
			ldx lbbexhi, y
			jsr win_setexec
			rts

;
;	Button exec functions
;

	.segment "DATA"
	
newpos:		.byte 0
	
	.segment "CODE"

updall:		jsr cur_hide
			jsr clr_lbitms
			jsr drw_lbitms
			ldy #LbStruct::wscrlind
			lda (lb_reg2), y
			jsr win_draw
			jmp cur_show

domove:		ldy #LbStruct::sel_line
			clc
			adc (lb_reg2), y
movesel:	sta newpos
			sec
			ldy #LbStruct::first_line
			sbc (lb_reg2), y
			bcs @gtfl
			lda newpos
			sta (lb_reg2), y
			jsr fixpos2
			jmp updall
@gtfl:		ldy #LbStruct::vis_lines
			cmp (lb_reg2), y
			bcc @ltvl
			jsr fixpos
			inc newpos
			sec
			lda newpos
			ldy #LbStruct::vis_lines
			sbc (lb_reg2), y
			ldy #LbStruct::first_line
			sta (lb_reg2), y
			jmp updall
@ltvl:		jsr cur_hide
			jsr lb_tglsel
			jsr fixpos
			jsr lb_tglsel
			jmp cur_show

fixpos:		lda newpos
fixpos2:	ldy #LbStruct::sel_line
			sta (lb_reg2), y
			rts

exup:		jsr lb_btnchck				; already at first line ?
			ldy #LbStruct::sel_line
			lda (lb_reg2), y
			beq @finexup
			lda #$FF
			jmp domove
@finexup:	rts

exdn:		jsr lb_btnchck				; already at last line ?
			ldy #LbStruct::sel_line
			lda (lb_reg2), y
			clc
			adc #1
			ldy #LbStruct::tot_lines
			cmp (lb_reg2), y
			bcs @finexdn
			lda #1
			jmp domove
@finexdn:	rts

exbeg:		jsr lb_btnchck				; already at first line ?
			ldy #LbStruct::sel_line
			lda (lb_reg2), y
			beq @finexbeg
			eor #$FF
			clc
			adc #1
			jmp domove
@finexbeg:	rts

exend:		jsr lb_btnchck				; already at last line ?
			clc
			ldy #LbStruct::tot_lines
			lda (lb_reg2), y
			ldy #LbStruct::sel_line
			sbc (lb_reg2), y
			beq @finexend
			jmp domove
@finexend:	rts

expgup:		jsr lb_btnchck				; already at first line ?
			ldy #LbStruct::sel_line
			lda (lb_reg2), y
			beq @finexpgup
			ldy #LbStruct::vis_lines
			cmp (lb_reg2), y
			bcs @fullscrl
			ldy #LbStruct::sel_line
@fullscrl:	lda (lb_reg2), y
			eor #$FF
			clc
			adc #1
			jmp domove 
@finexpgup:	rts			
			
expgdn:		jsr lb_btnchck				; already at last line ?
			clc
			ldy #LbStruct::tot_lines
			lda (lb_reg2), y
			ldy #LbStruct::sel_line
			sbc (lb_reg2), y
			beq @finexpgdn
			ldy #LbStruct::vis_lines
			cmp (lb_reg2), y
			bcc @partscrl
			lda (lb_reg2), y
@partscrl:	jmp domove
@finexpgdn:	rts

lb_btnchck:	jsr ex_button
			ldy #Event::type
			lda (reg2), y
			cmp #EVT_MOUSE_UP
			bne @brkexlbb
			jsr lb_selectw
			ldy #LbStruct::window
			lda (lb_reg2), y
			jsr win_select
			jmp win_begindraw

@brkexlbb:	pla						; pop return address
			pla
			rts
			
;
;	Scroll indicator draw function
;
drwscrlind:	jsr drw_window
			; draw frame
			lda #GM_CLEAR
			jsr g_mode
			jsr win_getpos
			stx lbscrlleft
			sty lbscrltop
			jsr g_moveto
			jsr win_getdim
			stx lbscrlrght
			sty lbscrlbot
			jsr g_vline
			; draw indicator
			inc lbscrlleft
			inc lbscrlleft
			inc lbscrltop
			sec
			lda lbscrlrght
			sbc #4
			sta lbscrlrght
			dec lbscrlbot
			dec lbscrlbot
			clc
			lda lbscrltop
			adc lbscrlbot
			sta lbscrlend
			ldx lbscrlleft
			ldy lbscrltop
			jsr g_moveto
			jsr lb_selectw
			ldy #LbStruct::vis_lines
			lda (lb_reg2), y
			ldy #LbStruct::tot_lines
			cmp (lb_reg2), y
			bcs @drwblk
			; calc size
			tax
			lda (lb_reg2), y
			sta lblines
			lda lbscrlbot
			sta lbscrlhgt
			jsr bmul
			ldy lblines
			jsr wdiv
			cpy #IND_MIN_HGT
			bcs @overmin
			ldy #IND_MIN_HGT
@overmin:	sty lbscrlbot
			; calc pos
			lda #GM_SET
			jsr g_mode
			ldy #LbStruct::first_line
			lda (lb_reg2), y
			beq @drwblk2
			tax
			lda lbscrlhgt
			jsr bmul
			ldy lblines
			jsr wdiv
			tya
			beq @drwblk2
			clc
			adc lbscrltop
			sta lbscrltop
 
			ldx lbscrlrght
			jsr g_block
			
 			ldx lbscrlleft
			ldy lbscrltop
			jsr g_moveto
			
@drwblk2:	lda #GM_CLEAR
			jsr g_mode
 
@drwblk:	ldx lbscrlrght
			ldy lbscrlbot
			jsr g_block
			
			; clear remaining area
			clc
			lda lbscrltop
			adc lbscrlbot
			cmp lbscrlend
			bcs	@findrw
			sta lbscrltop
			ldx lbscrlleft
			tay
			jsr g_moveto
			lda #GM_SET
			jsr g_mode
			sec
			lda lbscrlend
			sbc lbscrltop
			ldx lbscrlrght
			tay
			jsr g_block
@findrw:	rts

;
;	Find free ptr for a new LbStruct, alloc & assign memory
;	INPUT:
;		(lb_reg0) ... LbCreateStruct
;	OUTPUT:
;		(lb_reg2) ... new LbStruct
;		lbindex	.. LB table index
;
lb_alloc:	ldx #0
@next:		lda blptrhi, x
			beq @found
			inx
			cpx #LB_MAX_WINDOWS
			bcc @next
			jsr panic
@found:		stx lbindex
			lda #<.sizeof(LbStruct)	; Alloc struct
			ldx #>.sizeof(LbStruct)
			jsr malloc
			ldy lbindex				; Save ptr to reg & table 
			sta lb_reg2
			sta blptrlo, y
			stx lb_reg2+1
			txa
			sta blptrhi, y
			rts
;
;	Free LbStruct of table and clear table entry
;	INPUT:
;			lbindex .... Lb table index
;	
lb_free:	ldy lbindex
			lda blptrhi, y
			tax
			lda blptrlo, y
			jsr mfree
			ldx lbindex
			lda #0
			sta blptrlo, x
			sta blptrhi, x
			rts
 
;
;	Select LbStruct of table from window user value
;	INPUT:
;			user value of current window
;	OUTPUT:
;			(lb_reg2) ... new LbStruct
;	
lb_selectw:	jsr win_getuser
			sta lbindex			; select lb struct
			; fall through
;
;	Select LbStruct of table
;	INPUT:
;			lbindex .... Lb table index
;	OUTPUT:
;			(lb_reg2) ... new LbStruct
;	
lb_select:	ldx lbindex
			lda blptrlo, x
			sta lb_reg2
			lda blptrhi, x
			sta lb_reg2+1
			rts

;
;	Select LbCreateStruct of LbStruct
;	INPUT:
;		(lb_reg2) ... LbStruct
;	OUTPUT:
;		(lb_reg0) ... LbCreateStruct
;		(lb_reg1) ... LbColumnStruct [0]
;

lb_selconf:	ldy #LbStruct::config
			lda (lb_reg2), y
			sta lb_reg0
			iny
			lda (lb_reg2), y
			sta lb_reg0+1
			; fall through
;
;	Select LbColumnStruct of LbCreateStruct
;	INPUT:
;		(lb_reg0) ... LbCreateStruct
;	OUTPUT:
;		(lb_reg1) ... LbColumnStruct [0]
;

lb_selcol:	clc
			lda lb_reg0
			adc #<.sizeof(LbCreateStruct)
			sta lb_reg1
			lda lb_reg0+1
			adc #>.sizeof(LbCreateStruct)
			sta lb_reg1+1
			rts

;
;	Selects next column struct
;	INPUT:
;		(lb_reg1) ... LbColumnStruct[i]
;	OUTPUT:
;		(lb_reg1) ... LbColumnStruct[i+1]
;

lb_nextcol:	clc						; advance column struct ptr
			lda lb_reg1
			adc #<.sizeof(LbColumnStruct)
			sta lb_reg1
			lda lb_reg1+1
			adc #>.sizeof(LbColumnStruct)
			sta lb_reg1+1
			rts
			
;
;	Scroll bar button bitmaps
;

	.segment "RODATA"

datbeg:		.byte $F8, $20, $70, $70, $F8
datpgup:	.byte $20, $70, $F8, $20, $70, $F8
datup:		.byte $20, $20, $70, $70, $F8
datdn:		.byte $F8, $70, $70, $20, $20
datpgdn:	.byte $F8, $70, $20, $F8, $70, $20
datend:		.byte $F8, $70, $70, $20, $F8

bmbeg:		.byte 5, 5
			.word datbeg
bmpgup:		.byte 5, 6
			.word datpgup
bmup:		.byte 5, 5
			.word datup
bmdn:		.byte 5, 5
			.word datdn
bmpgdn:		.byte 5, 6
			.word datpgdn
bmend:		.byte 5, 5 
			.word datend

txbeg:		.byte $FF
			.word bmbeg
txpgup:		.byte $FF
			.word bmpgup
txup:		.byte $FF
			.word bmup
txdn:		.byte $FF
			.word bmdn
txpgdn:		.byte $FF
			.word bmpgdn
txend:		.byte $FF
			.word bmend
			
lbbtxlo:	.byte <txbeg, <txpgup, <txup, <txdn, <txpgdn, <txend
lbbtxhi:	.byte >txbeg, >txpgup, >txup, >txdn, >txpgdn, >txend

lbbexlo:	.byte <exbeg, <expgup, <exup, <exdn, <expgdn, <exend
lbbexhi:	.byte >exbeg, >expgup, >exup, >exdn, >expgdn, >exend
